/*
 * Copyright (c) 2023-2025 110476592@qq.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file draw_panel.h
 * @brief 截图工具 
 * @author 110476592@qq.com 
 * @note   承接Qt项目外包定制开发。长期接收C++项目实训学徒,联系QQ：110476592。
 */

 
#ifndef DRAW_PANEL_H
#define DRAW_PANEL_H
#include <common/global.h>
#include <QList>
#include <QMouseEvent>
#include <QPixmap>
#include <QPoint>
#include <QRect>
#include <QRubberBand>
#include <QVector>
#include <QWidget>
#include <drawboard/draw_record.h>
#include <widgets/toolbuttonex.h>
#include <list>
#include <queue>
/**
 * @brief  DrawPanel
 */

class AbsFloatToolBar; // 前置声明, 提高编译速度
class DrawPanel : public QWidget {
  Q_OBJECT

public:
  DrawPanel(const QRect &rect = QRect(0, 0, 800, 600),
            QWidget *parent = nullptr);
  ~DrawPanel();

  /**
   * @brief 获取选区的图像，如果没有选区，就获取整个图片
   * @return
   */
  QPixmap getSelectedPixmap();

  /**
   * @brief
   * 按屏幕的物理像素与设备无关像素之间的比率，进行选区转换，否则选区和截图位置会有偏差
   *
   */
  QRect toDevicePixelSelection();

  /**
   * @brief 保存切图为文件
   */
  void saveSelectedPixmap();

  /**
   * @brief 获取当前的工作模式
   * @return 当前的工作模式
   */
  inline WorkMode workMode() { return m_workMode; }

  /**
   * @brief 设置当前的工作模式
   * @param mode 要设置的工作模式
   */
  inline void setWorkMode(WorkMode mode) { m_workMode = mode; }

  /**
   * @brief 初始化工具栏
   */
  void init();

protected:
  virtual void paintEvent(QPaintEvent *event) override;
  virtual void mousePressEvent(QMouseEvent *event) override;
  virtual void mouseReleaseEvent(QMouseEvent *event) override;
  virtual void mouseMoveEvent(QMouseEvent *event) override;
  /**
   * @brief 键盘按下事件，按下ESC键时关闭窗口
   */
  virtual void keyPressEvent(QKeyEvent *) override;

  /**
 * @brief 创建浮动工具栏的虚函数。
 * 该函数用于创建浮动工具栏对象，并对其进行必要的初始化操作。
 * 子类可以重写此函数以实现自定义的工具栏创建逻辑。
 */
  virtual void createToolBar();


   /**
   * @brief handleCommand
   * @param cmd
   * @return true 如果没有自定义处理完了，就有处理handleCommand
   */
  virtual   bool handleCustomeCommand(ToolButtonEx *btn);

private:



  /**
   * @brief 更新选区模式下的鼠标图形
   */
  void updateDrawCursor();

  /**
   * @brief 绘制所有
   */
  void drawAll();

  /**
   * @brief drawOne
   * @param item
   */
  void drawOne(DrawRecord &item);

  /**
   * @brief 调整工具栏的位置
   */
  void updateToolBarPosition();

    /**
   * @brief 处理工具栏按钮命令
   * 该函数用于响应工具栏按钮的操作，根据不同的按钮执行相应的逻辑。
   * @param btn 触发命令的工具栏按钮对象指针
   */
  void handleCommand(ToolButtonEx *btn);

  /**
   * @brief 撤销上一步操作
   * 该函数将最近一次的绘制操作从绘制记录列表移动到撤销记录列表，
   * 并更新界面以显示撤销后的状态。
   */
  void undo();

  /**
   * @brief 重做上一步撤销的操作
   * 该函数将最近一次撤销的绘制操作从撤销记录列表移动回绘制记录列表，
   * 并更新界面以显示重做后的状态。
   */
  void redo();

  /**
   * @brief 清除所有绘制操作
   * 该函数将清空绘制记录列表和撤销记录列表，
   * 并更新界面以显示清空后的状态。
   */
  void clean();


protected:
  QPixmap m_pixmap;                          ///< 绘图的画布图像
  QPixmap m_originPixmap;                    ///< 绘图的画布图像
  bool m_leftPressed = false;                ///< 左键按下
  AbsFloatToolBar *m_floatToolBar = nullptr; ///< 浮动工具栏
  QRect m_selection = QRect(0, 0, 0, 0);     ///< 画板模式也设置选区，是为了兼容截屏模式
  std::list<DrawRecord> m_drawRecords; ///< 图形绘制数据列表，
                                       ///< 每次按下鼠标到提起记录一个元素。
  std::list<DrawRecord> m_undoRecords; ///< 存放被取消的操作图形绘制数据列表，
                                       ///< 取消的就加入这个队列。

  WorkMode m_workMode = WorkMode::AREA_SELECT; ///< 工作模式
};
#endif // SCREENSHOTWIDGET_H
